﻿using System;
using System.ComponentModel;
using System.IO;
using System.Xml.Serialization;
using HeritageAcademy.Shared;

namespace HeritageAcademy.Models.Loaders
{
    public class LoaderBase<T> : INotifyPropertyChanged
    {
        private T _model;
        private string _folder;
        private string _filename; 

        protected LoaderBase(T model)
        {
            Model = model;
        }

        public T Model
        {
            get { return _model; }
            private set
            {
                _model = value;
                RaisePropertyChanged("Model");
            }
        }

        public void Initialize(string folder, string filename)
        {
            _folder = folder;
            _filename = filename;
            
            string dataFilename = Path.Combine(_folder, _filename);

            //bool opened = false;
            if (File.Exists(dataFilename))
            {
                try
                {
                    Open(dataFilename);
                    //opened = true;
                }
                catch (Exception)
                {
                    // [TODO] Implement exception handler
                    throw new NotImplementedException();
                }
            }

            // [TODO] Decide the necessity of SampleData. May be to delete this part of code.
            /*
            // If the user has no data (or we can't open their data file), use the built-in sample data.
            if (!opened)
            {
                // We cannot read from our application resources when in design mode, 
                // so we construct some sample data instead.
                if (DesignerProperties.GetIsInDesignMode(Application.Current.MainWindow))
                {
                    _model = CreateSampleModelData();
                }
                else
                {
                    StreamResourceInfo info =
                        Application.GetResourceStream(new Uri("SampleModelData.xml", UriKind.Relative));
                    if (info != null)
                    {
                        using (Stream stream = info.Stream)
                        {
                            var serializer = new XmlSerializer(typeof(T));
                            _model = (T)serializer.Deserialize(stream);
                        }
                    }
                }
            }
            */
            //RefreshCollection();
        }

        /// <summary>
        /// Create sample data for design time.
        /// </summary>
        /// <returns>Sample data</returns>
        private static T CreateSampleModelData()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Refresh data collection after update.
        /// </summary>
        private static void RefreshCollection()
        {
        }

        /// <summary>
        /// Open data file.
        /// </summary>
        /// <param name="filename">Data file name</param>
        private void Open(string filename)
        {
            using (var fileStream = File.OpenRead(filename))
            {
                var serializer = new XmlSerializer(typeof(T));
                _model = (T)serializer.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Save data file.
        /// </summary>
        public void Save()
        {
            if (!Directory.Exists(_folder))
                Directory.CreateDirectory(_folder);
            SaveAs(Path.Combine(_folder, _filename));
        }

        /// <summary>
        /// Save data file under new name.
        /// </summary>
        /// <param name="filename">New data file name</param>
        private void SaveAs(string filename)
        {
            using (var fileStream = File.Open(filename, FileMode.Create))
            {
                var serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(fileStream, _model);
                //fileStream.Close(); -> CODE ANALYSIS WARRNING CA2202
            }
        }

        /// <summary>
        /// Property changed event handler.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
}